using FireStarter.Base;
using Firestarter.DB.Schema.BO;
using Firestarter.DB.Schema.Logic;
using Firestarter.DB.Schema.Test.Logic;
using Habanero.BO.ClassDefinition;
using Habanero.BO.Loaders;
using NUnit.Framework;

namespace SchemaInfo.Test.ReverseEngineer
{
    [TestFixture]
    public class TestDBReverseEng_PopulateInfos_Acceptance 
    {
        private TestUtilsDataTable _dataTableUtils;
        private DBSchemaBuilder _dbSchemaBuilder;
        private TestUtilsSchema _testUtilsSchema;
        private DatabaseReverseEngineerer _databaseReverseEngineerer;
        private DBSchemaExtractor_Fake _schemaExtractorFake;

        [TestFixtureSetUp]
        public  void TestFixtureSetup()
        {
            ClassDef.ClassDefs.Clear();
            string xmlClassDefs = BOBroker.GetClassDefsXml();
            ClassDef.ClassDefs.Add(new XmlClassDefsLoader(xmlClassDefs, new DtdLoader()).LoadClassDefs());
           // _dbSchemaBuilder = new DBSchemaBuilder();
            _dataTableUtils = new TestUtilsDataTable();
        }

        [SetUp]
        public  void SetupTest()
        {
            _schemaExtractorFake = new DBSchemaExtractor_Fake();
            _databaseReverseEngineerer = CreateDatabaseReverseEngineerer(_schemaExtractorFake);
            _dbSchemaBuilder = new DBSchemaBuilder();
            _testUtilsSchema = new TestUtilsSchema(_dbSchemaBuilder);
        }

        private DatabaseReverseEngineerer CreateDatabaseReverseEngineerer(DBSchemaExtractor_Fake dbSchemaExtractor)
        {
            return new DatabaseReverseEngineerer(new ReverseEngineeringSettings(), dbSchemaExtractor);
        }


        [TearDown]
        public void TearDownTest()
        {
            //runs every time any testmethod is complete
            //            base.TearDownTest();
        }
/*

        #region PopulateDBDatabase method
        [Test]
        public void Test_PopulateDatabaseInfo_OneTable()
        {
            //-------------Setup Test Pack ------------------
            const string tableName = "TestTable";
            _dbSchemaBuilder.CreateDatabaseTableWithIDAndNameField(tableName);
            DBDatabase databaseInfo = new DBDatabase();

            //-------------Test Pre-conditions --------------
            DBSchemaExtractorMySQL schemaExtractorMySQL = new DBSchemaExtractorMySQL();
            DataTable tableDataTable = schemaExtractorMySQL.GetTableDataTable(_databaseConnection.GetConnection());
            Assert.AreEqual(1, tableDataTable.Rows.Count);

            //-------------Execute test ---------------------
            _databaseReverseEngineer.PopulateDBDatabase(databaseInfo);

            //-------------Test Result ----------------------
            List<Table> tableInfos = databaseInfo.Tables;
            Assert.AreEqual(1, tableInfos.Count, "There should be one table in the db.");
            Table table = tableInfos[0];
            Assert.AreEqual(tableName.ToLower(), table.TableName);
            Assert.AreEqual("BASE TABLE", table.TableType);
            StringAssert.Contains("InnoDB free", table.TableComment);
            Assert.AreEqual(DateTime.Now.Year, table.CreateTime.Value.Year);
            Assert.AreEqual(null, table.UpdateTime);
            Assert.IsNotNull(table.Database, "Data base should be set even though the objects are not persisted");
            Assert.AreSame(databaseInfo, table.Database, "Data base should be set even though the objects are not persisted");
        }

        [Test]
        public void Test_PopulateDatabaseInfo_TwoTable()
        {
            //-------------Setup Test Pack ------------------
            const string tableName = "TestTable";
            _dataTableUtils.CreateDatabaseTableWithIDAndNameField(tableName);
            var testtable2 = tableName + "1";
            _dataTableUtils.CreateDatabaseTableWithIDAndNameField(testtable2);
            DBDatabase databaseInfo = new DBDatabase(_databaseConnection);

            //-------------Test Pre-conditions --------------

            //-------------Execute test ---------------------
            _databaseReverseEngineer.PopulateDBDatabase(databaseInfo);

            //-------------Test Result ----------------------
            List<Table> tableInfos = databaseInfo.Tables;
            Assert.AreEqual(2, tableInfos.Count, "There should be one table in the db.");
            Assert.IsNotNull(databaseInfo.GetTable(tableName.ToLower()));
            Assert.IsNotNull(databaseInfo.GetTable(testtable2.ToLower()));
        }

        [Test]
        public void Test_PopulateDatabaseInfoNoTablesDoesNotResultInError()
        {
            //---------------Set up test pack-------------------
            DBDatabase databaseInfo = new DBDatabase(_databaseConnection);

            //--------------Assert PreConditions----------------           
            //---------------Execute Test ----------------------
            _databaseReverseEngineer.PopulateDBDatabase(databaseInfo);
            List<Table> tableInfos = databaseInfo.Tables;

            //---------------Test Result -----------------------
            Assert.AreEqual(0, tableInfos.Count, "There should be no tables in the db");
        }

        [Test]
        public void Test_PopulateColumns_IDColumns()
        {
            //---------------Set up test pack-------------------
            const string tableName = "TestTable";
            _dataTableUtils.CreateDatabaseTableWithIDField(tableName);
            DBDatabase databaseInfo = new DBDatabase(_databaseConnection);
            Table tableInfo = new Table();
            databaseInfo.Tables.Add(tableInfo);

            //---------------Assert Precondition----------------
            Assert.AreSame(tableInfo.Database, databaseInfo);
            Assert.AreEqual(0, tableInfo.Columns.Count);

            //---------------Execute Test ----------------------
            _databaseReverseEngineer.PopulateColumns(tableInfo);

            //---------------Test Result -----------------------
            Assert.AreEqual(1, tableInfo.Columns.Count);
            const string columnName = tableName + "ID";
            Column columnInfo = tableInfo.Columns[0];
            Assert.AreEqual(columnName, columnInfo.ColumnName);
            Assert.AreEqual("char", columnInfo.DataType);
            Assert.AreEqual(38, columnInfo.DataLength);
            Assert.AreEqual(false, columnInfo.Nullable);
            Assert.IsTrue(string.IsNullOrEmpty(columnInfo.DefaultValue));
            Assert.IsFalse((bool)columnInfo.IsAutoIncrementing);
        }

        [Test]
        public void Test_PopulateColumns_ColumnDetailsCorrect_AutoIncrementing()
        {
            //---------------Set up test pack-------------------
            string tableName = TestUtils.GetRandomString();
            string columnName = TestUtils.GetRandomString();
            int dataLength = TestUtils.GetRandomInt(10, 100);
            _dataTableUtils.CreateDatabaseTableWithOneColumn(tableName, columnName, "int", dataLength, true, "NULL", true);
            DBDatabase databaseInfo = new DBDatabase(_databaseConnection);
            Table tableInfo = new Table(tableName);
            databaseInfo.Tables.Add(tableInfo);

            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            _databaseReverseEngineer.PopulateColumns(tableInfo);

            //---------------Test Result -----------------------
            List<Column> columnInfos = tableInfo.Columns;
            Assert.AreEqual(1, columnInfos.Count);
            Assert.AreEqual(columnName, columnInfos[0].ColumnName);
            Assert.AreEqual("int", columnInfos[0].DataType);
            Assert.AreEqual(dataLength, columnInfos[0].DataLength);
            Assert.AreEqual(false, columnInfos[0].Nullable); //auto incrementing makes nullable false
            Assert.AreEqual(null, columnInfos[0].DefaultValue);
            Assert.AreEqual(true, columnInfos[0].IsAutoIncrementing);
        }

        [Test]
        public void Test_PopulateColumns_ColumnDetailsCorrect_NonNullableChar()
        {
            //---------------Set up test pack-------------------
            string tableName = TestUtils.GetRandomString();
            string columnName = TestUtils.GetRandomString();
            int dataLength = TestUtils.GetRandomInt(40, 100);
            string defaultValue = TestUtils.GetRandomString();
            _dataTableUtils.CreateDatabaseTableWithOneColumn
                (tableName, columnName, "char", dataLength, false, string.Format("'{0}'", defaultValue));
            DBDatabase databaseInfo = new DBDatabase(_databaseConnection);
            Table tableInfo = new Table(tableName);
            databaseInfo.Tables.Add(tableInfo);

            //--------------Assert PreConditions----------------
            //---------------Execute Test ----------------------
            _databaseReverseEngineer.PopulateColumns(tableInfo);

            //---------------Test Result -----------------------
            List<Column> columnInfos = tableInfo.Columns;
            Assert.AreEqual(1, columnInfos.Count);
            Assert.AreEqual(columnName, columnInfos[0].ColumnName);
            Assert.AreEqual("char", columnInfos[0].DataType);
            Assert.AreEqual(dataLength, columnInfos[0].DataLength);
            Assert.AreEqual(false, columnInfos[0].Nullable);
            Assert.AreEqual(defaultValue, columnInfos[0].DefaultValue);
        }

        [Test]
        public void Test_PopulateColumns_ColumnDetailsCorrect_NonNullableInteger()
        {
            //---------------Set up test pack-------------------
            string tableName = TestUtils.GetRandomString();
            string columnName = TestUtils.GetRandomString();
            int dataLength = TestUtils.GetRandomInt(1, 10);
            string defaultValue = TestUtils.GetRandomInt(1, 10).ToString();
            _dataTableUtils.CreateDatabaseTableWithOneColumn
                (tableName, columnName, "int", dataLength, false, string.Format("'{0}'", defaultValue));
            DBDatabase databaseInfo = new DBDatabase(_databaseConnection);
            Table tableInfo = new Table(tableName);
            databaseInfo.Tables.Add(tableInfo);

            //--------------Assert PreConditions----------------
            //---------------Execute Test ----------------------
            _databaseReverseEngineer.PopulateColumns(tableInfo);

            //---------------Test Result -----------------------
            List<Column> columnInfos = tableInfo.Columns;
            Assert.AreEqual(1, columnInfos.Count);
            Assert.AreEqual(columnName, columnInfos[0].ColumnName);
            Assert.AreEqual("int", columnInfos[0].DataType);
            Assert.AreEqual(dataLength, columnInfos[0].DataLength);
            Assert.AreEqual(false, columnInfos[0].Nullable);
            Assert.AreEqual(defaultValue, columnInfos[0].DefaultValue);
        }

        [Test]
        public void Test_PopulateColumns_ColumnDetailsCorrect_NullableChar()
        {
            //---------------Set up test pack-------------------
            string tableName = TestUtils.GetRandomString();
            string columnName = TestUtils.GetRandomString();
            int dataLength = TestUtils.GetRandomInt(10, 100);
            _dataTableUtils.CreateDatabaseTableWithOneColumn(tableName, columnName, "char", dataLength, true, "NULL");
            DBDatabase databaseInfo = new DBDatabase(_databaseConnection);
            Table tableInfo = new Table(tableName);
            databaseInfo.Tables.Add(tableInfo);
            //--------------Assert PreConditions----------------
            //---------------Execute Test ----------------------
            _databaseReverseEngineer.PopulateColumns(tableInfo);
            //---------------Test Result -----------------------
            List<Column> columnInfos = tableInfo.Columns;
            Assert.AreEqual(1, columnInfos.Count);
            Assert.AreEqual(columnName, columnInfos[0].ColumnName);
            Assert.AreEqual("char", columnInfos[0].DataType);
            Assert.AreEqual(dataLength, columnInfos[0].DataLength);
            Assert.AreEqual(false, columnInfos[0].Nullable);
            Assert.AreEqual(null, columnInfos[0].DefaultValue);
            Assert.AreEqual(false, columnInfos[0].IsAutoIncrementing);
        }

        [Test]
        public void Test_PopulatePrimaryKey()
        {
            //---------------Set up test pack-------------------
            string tableName = TestUtils.GetRandomString();
            _dataTableUtils.CreateDatabaseTableWithIDAndNameField(tableName);
            Table tableInfo = CreatePopulatedTableInfo(tableName);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            _databaseReverseEngineer.PopulatePrimaryKeyInfos(tableInfo);
            //---------------Test Result -----------------------
            Assert.IsNotNull(tableInfo.PrimaryKey);
            BusinessObjectCollection<Column> primaryKeyColumns = tableInfo.PrimaryKey.Columns;
            Assert.AreEqual(1, primaryKeyColumns.Count);
            Assert.AreEqual(tableName + "ID", primaryKeyColumns[0].ColumnName);
        }

        [Test]
        public void Test_PopulateAlternateKey()
        {
            //---------------Set up test pack-------------------
            string tableName = TestUtils.GetRandomString();
            string keyColumnName = TestUtils.GetRandomString();
            _dataTableUtils.CreateDatabaseTableWithIDAndSpecifiedFieldAsKey(tableName, keyColumnName);
            Table tableInfo = CreatePopulatedTableInfo(tableName);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            _databaseReverseEngineer.PopulateAlternateKeyInfos(tableInfo);
            //---------------Test Result -----------------------
            Assert.IsNotNull(tableInfo.Keys);
            Assert.AreEqual(1, tableInfo.Keys.Count);
            DBKey keyInfo = tableInfo.Keys[0];
            Assert.AreEqual(1, keyInfo.KeyColumns.Count);
            Assert.IsNotNull(keyInfo.KeyColumns[0].Column);
            Assert.AreEqual(keyColumnName, keyInfo.KeyColumns[0].Column.ColumnName);
        }

        [Test]
        public void Test_PopulateForeignKey()
        {
            //---------------Set up test pack-------------------
            string foreignKeyTableName = TestUtils.GetRandomString();
            string referencedTableName = TestUtils.GetRandomString();
            string foreignKeyColumnName = TestUtils.GetRandomString();
            string referencedTableColumnName = TestUtils.GetRandomString();
            _dataTableUtils.CreateDatabaseTablesWithForeignKey(foreignKeyTableName, referencedTableName, foreignKeyColumnName, referencedTableColumnName);
            Table referencedTableInfo = CreatePopulatedTableInfo(referencedTableName);
            Table foreignKeyTableInfo = CreatePopulatedTableInfo(foreignKeyTableName, referencedTableInfo.Database);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            _databaseReverseEngineer.PopulateForeignKeys(foreignKeyTableInfo);
            //---------------Test Result -----------------------
            Assert.IsNotNull(foreignKeyTableInfo.ForeignKeys);
            Assert.AreEqual(1, foreignKeyTableInfo.ForeignKeys.Count);
            DBForeignKey foreignKeyInfo = foreignKeyTableInfo.ForeignKeys[0];
            Assert.AreEqual(referencedTableName, foreignKeyInfo.RelatedTable.TableName);
            Assert.AreEqual(1, foreignKeyInfo.ForeignKeyColumns.Count);
            Assert.AreEqual(referencedTableColumnName, foreignKeyInfo.ForeignKeyColumns[0].RelatedColumnInfoName);
        }

        [Test]
        public void Test_Populate_CompleteAcceptanceTest()
        {
            //---------------Set up test pack-------------------
            string foreignKeyTableName = TestUtils.GetRandomString();
            string referencedTableName = TestUtils.GetRandomString();
            string foreignKeyColumnName = TestUtils.GetRandomString();
            string referencedTableColumnName = TestUtils.GetRandomString();
            _dataTableUtils.CreateDatabaseTablesWithForeignKeyAndAlternateKey(foreignKeyTableName, referencedTableName, foreignKeyColumnName, referencedTableColumnName);
            DBDatabase databaseInfo = new DBDatabase(_databaseConnection);
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            _databaseReverseEngineer.PopulateDBDatabase(databaseInfo);
            //---------------Test Result -----------------------
            Assert.AreEqual(2, databaseInfo.Tables.Count);

            Table referencedTableInfo = databaseInfo.GetTable(referencedTableName);
            Assert.AreEqual(referencedTableName, referencedTableInfo.TableName);
            Assert.AreEqual(1, referencedTableInfo.Columns.Count);
            Assert.IsNotNull(referencedTableInfo.PrimaryKey);
            Assert.AreEqual(1, referencedTableInfo.PrimaryKey.Columns.Count);
            Assert.AreEqual(0, referencedTableInfo.Keys.Count);
            Assert.AreEqual(0, referencedTableInfo.ForeignKeys.Count);

            Table foreignKeyTableInfo = databaseInfo.GetTable(foreignKeyTableName);
            Assert.AreEqual(foreignKeyTableName, foreignKeyTableInfo.TableName);
            Assert.AreEqual(2, foreignKeyTableInfo.Columns.Count);
            Assert.IsNotNull(foreignKeyTableInfo.PrimaryKey);
            Assert.AreEqual(1, foreignKeyTableInfo.PrimaryKey.Columns.Count);
            Assert.AreEqual(1, foreignKeyTableInfo.Keys.Count);
            Assert.AreEqual(1, foreignKeyTableInfo.ForeignKeys.Count);
        }
        #endregion

        #region Utils

        private Table CreatePopulatedTableInfo(string tableName)
        {
            DBDatabase databaseInfo = new DBDatabase(_databaseConnection);
            return CreatePopulatedTableInfo(tableName, databaseInfo);
        }

        private static Table CreatePopulatedTableInfo(string tableName, DBDatabase databaseInfo)
        {
            Table tableInfo = new Table(tableName);
            databaseInfo.Tables.Add(tableInfo);
            _databaseReverseEngineer.PopulateColumns(tableInfo);
            return tableInfo;
        }


        #endregion*/
    }
}
